#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>


#define N 5
#define LEFT (i+N-1)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY   1
#define EATING   2

int noodles=100;
int state[N];
pthread_mutex_t mutex =
 PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t f[N];
void check_state(int i)
{
 if (state[i]==HUNGRY&&state[LEFT]!=EATING
&&state[RIGHT]!= EATING){
        state[i] = EATING;
        pthread_mutex_unlock(&f[i]);
    }
}
void get_forks(int i)
{ pthread_mutex_lock(&mutex);
    state[i] = HUNGRY;
    check_state(i);
    pthread_mutex_unlock(&mutex);
    pthread_mutex_lock(&f[i]);
}
void return_forks(int i)
{ pthread_mutex_lock(&mutex);
    state[i] = THINKING;
    check_state(LEFT);
    check_state(RIGHT);
    pthread_mutex_unlock(&mutex);
}
void eat(int i)
{ noodles--;
    if(noodles<0){			//0.end check
    printf("the  %d thread die\n", i);
    pthread_exit (NULL);
    }
    printf("phi %d is eating,\t and noodle is left %d \n",i,noodles);
    sleep(4);
}
void* phi(void* date)
{ int i = *(int*)date;
    while (1) {
	if(noodles<0){			//0.end check
	 printf("the  %d thread die\n", i);
	 pthread_exit (NULL);
	}
        sleep(1);			//1.equal thinking 	
        get_forks(i);			//2.equal get_fork
		eat(i);				//3.equal eating
        return_forks(i);		//4.equal return_fork
}
    return NULL;}
int main()
{ int i; printf("there is %d  noodles.\n",noodles);
    pthread_t th[N];
    for (i = 0; i < N; i++)
    {
	state[i]=THINKING;
	pthread_create(&th[i], NULL, phi, (void*)(&i));
    }
    for (i = 0; i < N;i++)pthread_join(th[i], NULL);
    return 0;}
